﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Resources;
using System.Threading;
using System.Data;



#pragma warning disable 0472

/// <summary>
/// Currencies
/// </summary>
public enum Currencies
{
    ///<summary>United Arab Emirates Dirham (AED)</summary>
    AED,

    ///<summary>Netherlands Antillean Guilder (ANG)</summary>
    ANG,

    ///<summary>Argentine Peso (ARS)</summary>
    ARS,

    ///<summary>Australian Dollar (AUD)</summary>
    AUD,

    ///<summary>Bangladeshi Taka (BDT)</summary>
    BDT,

    ///<summary>Bulgarian Lev (BGN)</summary>
    BGN,

    ///<summary>Bahraini Dinar (BHD)</summary>
    BHD,

    ///<summary>Brunei Dollar (BND)</summary>
    BND,

    ///<summary>Bolivian Boliviano (BOB)</summary>
    BOB,

    ///<summary>Brazilian Real (BRL)</summary>
    BRL,

    ///<summary>Botswanan Pula (BWP)</summary>
    BWP,

    ///<summary>Canadian Dollar (CAD)</summary>
    CAD,

    ///<summary>Swiss Franc (CHF)</summary>
    CHF,

    ///<summary>Chilean Peso (CLP)</summary>
    CLP,

    ///<summary>Chinese Yuan (CNY)</summary>
    CNY,

    ///<summary>Colombian Peso (COP)</summary>
    COP,

    ///<summary>Costa Rican Col�n (CRC)</summary>
    CRC,

    ///<summary>Czech Republic Koruna (CZK)</summary>
    CZK,

    ///<summary>Danish Krone (DKK)</summary>
    DKK,

    ///<summary>Dominican Peso (DOP)</summary>
    DOP,

    ///<summary>Algerian Dinar (DZD)</summary>
    DZD,

    ///<summary>Estonian Kroon (EEK)</summary>
    EEK,

    ///<summary>Egyptian Pound (EGP)</summary>
    EGP,

    ///<summary>Euro (EUR)</summary>
    EUR,

    ///<summary>Fijian Dollar (FJD)</summary>
    FJD,

    ///<summary>British Pound Sterling (GBP)</summary>
    GBP,

    ///<summary>Hong Kong Dollar (HKD)</summary>
    HKD,

    ///<summary>Honduran Lempira (HNL)</summary>
    HNL,

    ///<summary>Croatian Kuna (HRK)</summary>
    HRK,

    ///<summary>Hungarian Forint (HUF)</summary>
    HUF,

    ///<summary>Indonesian Rupiah (IDR)</summary>
    IDR,

    ///<summary>Israeli New Sheqel (ILS)</summary>
    ILS,

    ///<summary>Indian Rupee (INR)</summary>
    INR,

    ///<summary>Jamaican Dollar (JMD)</summary>
    JMD,

    ///<summary>Jordanian Dinar (JOD)</summary>
    JOD,

    ///<summary>Japanese Yen (JPY)</summary>
    JPY,

    ///<summary>Kenyan Shilling (KES)</summary>
    KES,

    ///<summary>South Korean Won (KRW)</summary>
    KRW,

    ///<summary>Kuwaiti Dinar (KWD)</summary>
    KWD,

    ///<summary>Cayman Islands Dollar (KYD)</summary>
    KYD,

    ///<summary>Kazakhstani Tenge (KZT)</summary>
    KZT,

    ///<summary>Lebanese Pound (LBP)</summary>
    LBP,

    ///<summary>Sri Lankan Rupee (LKR)</summary>
    LKR,

    ///<summary>Lithuanian Litas (LTL)</summary>
    LTL,

    ///<summary>Latvian Lats (LVL)</summary>
    LVL,

    ///<summary>Moroccan Dirham (MAD)</summary>
    MAD,

    ///<summary>Moldovan Leu (MDL)</summary>
    MDL,

    ///<summary>Macedonian Denar (MKD)</summary>
    MKD,

    ///<summary>Mauritian Rupee (MUR)</summary>
    MUR,

    ///<summary>Maldivian Rufiyaa (MVR)</summary>
    MVR,

    ///<summary>Mexican Peso (MXN)</summary>
    MXN,

    ///<summary>Malaysian Ringgit (MYR)</summary>
    MYR,

    ///<summary>Namibian Dollar (NAD)</summary>
    NAD,

    ///<summary>Nigerian Naira (NGN)</summary>
    NGN,

    ///<summary>Nicaraguan C�rdoba (NIO)</summary>
    NIO,

    ///<summary>Norwegian Krone (NOK)</summary>
    NOK,

    ///<summary>Nepalese Rupee (NPR)</summary>
    NPR,

    ///<summary>New Zealand Dollar (NZD)</summary>
    NZD,

    ///<summary>Omani Rial (OMR)</summary>
    OMR,

    ///<summary>Peruvian Nuevo Sol (PEN)</summary>
    PEN,

    ///<summary>Papua New Guinean Kina (PGK)</summary>
    PGK,

    ///<summary>Philippine Peso (PHP)</summary>
    PHP,

    ///<summary>Pakistani Rupee (PKR)</summary>
    PKR,

    ///<summary>Polish Zloty (PLN)</summary>
    PLN,

    ///<summary>Paraguayan Guarani (PYG)</summary>
    PYG,

    ///<summary>Qatari Rial (QAR)</summary>
    QAR,

    ///<summary>Romanian Leu (RON)</summary>
    RON,

    ///<summary>Serbian Dinar (RSD)</summary>
    RSD,

    ///<summary>Russian Ruble (RUB)</summary>
    RUB,

    ///<summary>Saudi Riyal (SAR)</summary>
    SAR,

    ///<summary>Seychellois Rupee (SCR)</summary>
    SCR,

    ///<summary>Swedish Krona (SEK)</summary>
    SEK,

    ///<summary>Singapore Dollar (SGD)</summary>
    SGD,

    ///<summary>Slovak Koruna (SKK)</summary>
    SKK,

    ///<summary>Sierra Leonean Leone (SLL)</summary>
    SLL,

    ///<summary>Salvadoran Col�n (SVC)</summary>
    SVC,

    ///<summary>Thai Baht (THB)</summary>
    THB,

    ///<summary>Tunisian Dinar (TND)</summary>
    TND,

    ///<summary>Turkish Lira (TRY)</summary>
    TRY,

    ///<summary>Trinidad and Tobago Dollar (TTD)</summary>
    TTD,

    ///<summary>New Taiwan Dollar (TWD)</summary>
    TWD,

    ///<summary>Tanzanian Shilling (TZS)</summary>
    TZS,

    ///<summary>Ukrainian Hryvnia (UAH)</summary>
    UAH,

    ///<summary>Ugandan Shilling (UGX)</summary>
    UGX,

    ///<summary>US Dollar (USD)</summary>
    USD,

    ///<summary>Uruguayan Peso (UYU)</summary>
    UYU,

    ///<summary>Uzbekistan Som (UZS)</summary>
    UZS,

    ///<summary>Venezuelan Bol�var (VEF)</summary>
    VEF,

    ///<summary>Vietnamese Dong (VND)</summary>
    VND,

    ///<summary>CFA Franc BCEAO (XOF)</summary>
    XOF,

    ///<summary>Yemeni Rial (YER)</summary>
    YER,

    ///<summary>South African Rand (ZAR)</summary>
    ZAR,

    ///<summary>Zambian Kwacha (ZMK)</summary>
    ZMK,


}



namespace CurrencyConverter
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void OperationCompletedEventHandler(object sender, OperationCompletedEventArgs e);
    /// <summary>
    /// 
    /// </summary>
    public class OperationCompletedEventArgs : EventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        private string result;
        private List<string> ResultList;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="result"></param>
        public void SetResult(string result)
        {
            if (result == null) throw new  NullReferenceException();
            this.result = result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="List"></param>
        public void SetResult(List<string> List)
        {
            if (List == null) throw new NullReferenceException();
            this.ResultList = List;
        }

        /// <summary>
        /// 
        /// </summary>
        public string Result
        {
            get { return result; }
        }
        /// <summary>
        /// 
        /// </summary>
        public List<string> ListResult
        { 
            get { return ResultList; }
        }

    }
    /// <summary>
    /// Currency Converter Class 1.0
    /// </summary>
   public class Converter
    {

       /// <summary>
       /// OnCompleted Event
       /// </summary>
       public event OperationCompletedEventHandler OnCompleted;

        
        /// <summary>
        /// Google API
        /// </summary>
        private const string GoogleAPI = "http://www.google.com/finance/converter?a=";

     
       /// <summary>
       /// Result Formatting Options
       /// </summary>
        public  enum ResultFormatting
        {
            /// <summary>
            /// return only Converted Value
            /// </summary>
           OnlyConvertedValue,  
            /// <summary>
            /// return a Converted Value with Description ex 100 U.S Dollar
            /// </summary>
           ConvertedValueDescription,
            /// <summary>
            /// return a Converted Value and From Value ex 1 EUR = 1.4 USD
            /// </summary>
           ConvertedValueAndFromAmount,
            /// <summary>
            ///  Return Array for All Option
            /// </summary>
            All,
                
           
        }
        /// <summary>
        /// Init()
        /// </summary>
        public Converter()
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
                                       
        }

        /// <summary>
        /// A three letter currency code (From Currency)
        /// </summary>
        public Currencies From { get; set; }
        /// <summary>
        /// A three letter currency code (To Currency)
        /// </summary>
        public Currencies To { get; set; }
        /// <summary>
        /// amount
        /// </summary>
        public double amount { get; set; }

        private WebClient wc;
        private ResultFormatting m_Formatting;
        /// <summary>
        /// Result of Conversion
        /// </summary>
        /// <returns>Return only numerical value</returns>
        public void Result(ResultFormatting Formatting)
        {

                m_Formatting = Formatting;

            if (From == null || To == null || amount == 0)
                return;

            if (From == To)
            {
                OperationCompletedEventArgs Return = new OperationCompletedEventArgs();
                Return.SetResult(Convert.ToString(amount));
                OnCompleted(this, Return);
                return;
            }
                
        
                    string Str = "";
                    Str = amount + "&from=" + From + "&to=" + To;

                           
                            wc = new WebClient();
                            wc.Proxy = null;
                            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);

                            wc.DownloadStringAsync(new Uri(GoogleAPI + Str));
        }

       private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {

            if (m_Formatting == null)
                m_Formatting = ResultFormatting.ConvertedValueDescription;

         OperationCompletedEventArgs Event = new OperationCompletedEventArgs();

           Event.SetResult("Error");

           string Data = e.Result;

             Data = Data.Replace("&nbsp;", "*");

                string[] Tmp = Data.Split('*');

                Regex Regexp = new Regex(@"<div id=currency_converter_result>([\w\s-.]+[\w\-.]) = <span class=bld>([\w\s-.]+[\w\-.])</span>");
                Match m = Regexp.Match(Tmp[1]);

           
                if (m.Success)
                {

                    string[] Ret = m.Groups[2].Value.Split(' ');
              
                   
                    switch (m_Formatting)
                    {
                        case ResultFormatting.ConvertedValueAndFromAmount:
                            Event.SetResult(m.Groups[1].Value + " = " + m.Groups[2]);
                            break;

                        case ResultFormatting.ConvertedValueDescription:
                            Event.SetResult(Ret[0] + " " + GetDescriptionOfISOCode(To));
                            break;
                        case ResultFormatting.OnlyConvertedValue:
                            Event.SetResult(Ret[0]);
                            break;
                        case ResultFormatting.All:
                            List<string> List = new List<string>();
                            List.Add(m.Groups[1].Value + " = " + m.Groups[2]); // ConvertedValueAndFromAmount
                            List.Add(Ret[0] + " " + GetDescriptionOfISOCode(To)); // ConvertedValueDescription
                            List.Add(Ret[0]); // OnlyConvertedValue

                            Event.SetResult(List);

                            break;
                       }
                        

                    

                   
                    OnCompleted(sender, Event);
                }
          
              
        }
  

        /// <summary>
        /// Result of Conversion
        /// </summary>
        /// <param name="from">A three letter currency code (From Currency)</param>
        /// <param name="to">A three letter currency code (To Currency)</param>
        /// <param name="amount">amount</param>
        /// <param name="Formatting">Formmatting option</param>
        /// <returns>Return only numerical value</returns>
        public void Result(Currencies from, Currencies to, double amount,ResultFormatting Formatting)
        {
            this.From = from;
            this.To = to;
            this.amount = amount;
            this.Result(Formatting);
                     

        }

     
        /// <summary>
        /// To Reverse between Form and To 
        /// To get the result, you should call Result() or ResultEx() Function after calling Reverse()
        /// </summary>
        /// <returns>True If Sucess</returns>
        public bool Reverse()
        {
            
            if (From == null || To == null)
                return false;

            Currencies OldFrom = From;
            From = To;
            To = OldFrom;
            
            
            return true;
        }

        /// <summary>
        /// Description of an ISO Code 
        /// </summary>
        /// <param name="Code"></param>
        /// <returns>String</returns>
        public string GetDescriptionOfISOCode(string Code)
        {
            DataSet DataSet = LoadFromXml();
            string Ret = "";
            List<string> List = new List<string>();

            foreach (DataRow Row in DataSet.Tables["Currency"].Rows)
            {
                foreach (object item in Row.ItemArray)
                {
                    List.Add(item.ToString());
                }
            }

                int i = List.IndexOf(Code);
           
                Ret = List[i + 1];


          return Ret;

        }

        /// <summary>
        /// Description of an ISO Code 
        /// </summary>
        /// <param name="Code">Currencies</param>
        /// <returns>String</returns>
        public string GetDescriptionOfISOCode(Currencies Code)
        {
          return  GetDescriptionOfISOCode(Enum.GetName(typeof(Currencies),Code));
        }

        private DataSet LoadFromXml()
        {
            DataSet DataSet = new System.Data.DataSet();
            
            if (!File.Exists("Currencies"))
            {
                File.WriteAllText("Currencies.xml", CurrencyConverter.Properties.Resources.Currencies);

                DataSet.ReadXml("Currencies.xml");

            }
            else { DataSet.ReadXml("Currencies.xml"); }
            return DataSet;
        }


        /// <summary>
        /// Obtain dataSet of Currencies and their description.
        /// </summary>
        /// <returns></returns>
        public DataSet GetDataSet()
        {
            return LoadFromXml();
        }



    }
#pragma warning restore 0472
}
